#include "http.h"
#include "hdr.h"

action_function g_act[F_SIZE];
int g_act_idx = 0;

session g_session[MAX_SESSION_CHAIN];
position g_position[MAX_POSITION_CHAIN];
int g_position_pos = 0;

int init_position()
{
	memset(&g_position, 0, MAX_POSITION_CHAIN * sizeof(position));
}
char * pop_position()
{
	if(g_position_pos>=0)
	{
		*g_position[g_position_pos].p = g_position[g_position_pos].bck;
		return g_position[g_position_pos--].p;
	}
	_assert(0);
	return NULL;
}
void push_position(char * p, char c)
{
	if(g_position_pos<MAX_POSITION_CHAIN)
	{
		g_position_pos++;
		g_position[g_position_pos].bck = * p;
		g_position[g_position_pos].p = p;
		*p=c;
		return;
	}
	_assert(0);

}
buffer * malloc_buffer(size_t size)
{
	buffer * bf = (buffer *)malloc(sizeof(buffer));
	bf->pbuff = (char*)malloc(size*sizeof(char));
	memset(bf->pbuff, 0, size*sizeof(char) );
	bf->buff_size = size;
	bf->used_size = 0;
	return bf;
}
http_request * malloc_request()
{
	http_request * rqst = NULL;
	rqst = (http_request *)malloc(sizeof(http_request));
	rqst->host = malloc_buffer(HOST_LEN);
	rqst->uri  = malloc_buffer(URI_LEN);
	rqst->rq_type = 0;
	rqst->request_session = NULL;
	return rqst;
}
//HEED:
int free_session(http_request * rqst)
{
	session_pair * ses = rqst->request_session;
	if (ses == NULL)
	{
		return R_OK;
	}
	ses->is_null = 1;
}
int free_data(http_request * rqst)
{
	request_data * p ;

	p = rqst->post_date;
	while(p!=NULL)
	{
		request_data * pn = p->next;
		free_buffer(p->name);
		free_buffer(p->value);
		free(p);
		p = pn;
	}
}
int free_request(http_request * rqst)
{
	if (rqst == NULL)
	{
		return R_OK;
	}
	free_buffer(rqst->host);
	free_buffer(rqst->uri);
	free_session(rqst);
	free_data(rqst);
	return R_OK;
}

int bzero_buffer(buffer * bf)
{
	return 1;
}
int copy_buffer(buffer * src, buffer * dst)
{
	int src_size = 0;
	if(src==NULL||dst==NULL)
	{
		return R_ERR;
	}
	src_size = src->used_size;
	if(src->used_size>dst->used_size)
	{
		src_size = dst->used_size;
	}
	memcpy(dst->pbuff, src->pbuff, src_size);
	dst->used_size = src_size;
	return R_OK;
}
int copy_string_to_buffer(char * src, buffer * dst, int len)
{
	if(src==NULL||dst==NULL)
	{
		return R_ERR;
	}
	if(len>dst->buff_size)
	{
		len = dst->buff_size;
	}
	memcpy(dst->pbuff, src, len);
	dst->used_size = len;
	return R_OK;
}
int free_buffer(buffer *bf)
{
	if(bf!=NULL)
	{
		if(bf->pbuff!=NULL)
		{
			free(bf->pbuff);
		}
		free(bf);
		bf=NULL;
	}
}
int print_buffer(buffer * bf)
{
	if(bf == NULL)
	{
		printf("no data exists");
	}
	printf("%s\n", bf->pbuff);
}
session * get_a_free_session()
{
	int i = 0;
	for(i=0;i<MAX_SESSION_CHAIN;i++)
	{
		if(g_session[i].is_null == 1)
		{
			return &g_session[i];
		}
	}
}
request_data * malloc_data_pair()
{
	request_data * tmp = NULL;
	tmp = (request_data * )malloc(sizeof(request_data));
	tmp->name = malloc_buffer(DATA_NAME_LEN);
	tmp->value = malloc_buffer(DATA_VALUE_LEN);
	tmp->next = NULL;
	return tmp;
}

int init_session()
{
	int i = 0;
	for (i=0;i<MAX_SESSION_CHAIN;i++)
	{
		g_session[i].pair = (session_pair*)malloc(sizeof(session_pair));
		g_session[i].pair->session_name  = malloc_buffer(SESSION_NAME_SIZE);
		g_session[i].pair->session_value = malloc_buffer(SESSION_VALUE_SIZE);
		g_session[i].is_null = 1;
	}
}
//////////////////////////////////////////////////////////////////////////
int init_http()
{
	int i = 0;
	//init global session buffer
	init_session();

	//init position
	init_position();

	//init functions
	memset(g_act, F_SIZE * sizeof(action_function));

}
 
int parse_request(char * bf, http_request * http_rqt)
{
	char * delimiter = NULL;
	char * temp_p = NULL;
	
	int temp_len = 0;
	if(bf==NULL||http_rqt==NULL)
	{
		return R_ERR;
	}
	if (delimiter = strstr(bf, "GET"))
	{
		http_rqt->rq_type = HTTP_GET;
	}
	else if (delimiter = strstr(bf, "POST"))
	{
		http_rqt->rq_type = HTTP_POST;
	}
	else
	{
		return R_ERR;
	}

	//get uri
	delimiter += 4;
	if(!(temp_p = strstr(delimiter, " ")))
	{
		return R_ERR;
	}
	temp_len = temp_p - delimiter;
	copy_string_to_buffer(delimiter, http_rqt->host, temp_len);
	print_buffer(http_rqt->host);

	//get host
	if ((delimiter = strstr(delimiter, "Host:"))==NULL)
	{
		return R_ERR;
	}
	delimiter += 6;
	if(!(temp_p = strstr(delimiter, "\r\n")))
	{
		return R_ERR;
	}
	temp_len = temp_p - delimiter;
	copy_string_to_buffer(delimiter, http_rqt->uri, temp_len);
	print_buffer(http_rqt->uri);

	//get cookie
	if (delimiter = strstr(delimiter, "Cookie:"))
	{
		
		session * ses = get_a_free_session();

		delimiter += 8;
		if(!(temp_p = strstr(delimiter, "\r\n")))
		{
			return R_ERR;
		}
		
		push_position(temp_p, 0);
		
		if(!(temp_p = strstr(delimiter, SESSION_TOKEN)))
		{
			//no session_id found
			http_rqt->request_session = NULL;
		}
		else
		{
			int multi_session = 0;
			if((temp_p = strstr(delimiter, ";")))
			{
				push_position(temp_p,0);
				multi_session = 1;
			}
			if((temp_p = strstr(delimiter, "=")))
			{
				//this is what session we want
				push_position(temp_p, 0);
				copy_string_to_buffer(delimiter, ses->pair->session_name, strlen(delimiter));
				delimiter = temp_p+1;
				pop_position();
				copy_string_to_buffer(delimiter, ses->pair->session_value, strlen(delimiter));
			}
			if(multi_session)
			{
				pop_position();
			}
		}
		pop_position();
		
		print_buffer(ses->pair->session_name);
		print_buffer(ses->pair->session_value);
	}
	if(http_rqt->rq_type == HTTP_POST)
	{
		int pushed = 0;
		request_data * data = NULL;
		
		//get post data
		if (delimiter = strstr(delimiter, "\r\n\r\n"))
		{
			delimiter += 4;
		}
		while(1)
		{
			int loop_end = 0;
			pushed = 0;
			if (temp_p = strstr(delimiter, "="))
			{
				push_position(temp_p,0);
			}
			if( data == NULL )
			{
				data = malloc_data_pair();
				http_rqt->post_date = data;
			}
			else
			{
				data->next = malloc_data_pair();
				data = data->next;
			}

			//retrieve name
			copy_string_to_buffer(delimiter, data->name, strlen(delimiter));
			pop_position();
			delimiter = temp_p + 1;
			if (temp_p = strstr(delimiter, "&"))
			{
				push_position(temp_p,0);
				pushed = 1;
			}
			else
			{
				loop_end = 1;
			}
			copy_string_to_buffer(delimiter, data->value, strlen(delimiter));
			if (pushed)
			{
				pop_position();
			}
			delimiter = temp_p+1;
			if (loop_end)
			{
				break;
			}
			
		}
		{//just for test
			request_data * d = http_rqt->post_date;
			while(d)
			{			
				print_buffer(d->name);
				print_buffer(d->value);	
				d=d->next;
			}
		}
	}
	return R_OK;


}

int http_main(char * buff)
{
	http_request * rqst = NULL;
	
	init_http();
	rqst = malloc_request();
	
	if(parse_request(buff, rqst ) == R_ERR)
	{
		PT("error\n\n");
	}


	free_request(rqst);



}